use std::collections::HashMap;
use std::path::PathBuf;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ProjectType {
    Executable,
    StaticLibrary,
    DynamicLibrary,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum BuildConfiguration {
    Debug,
    Release,
    Custom(String),
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SourceFile {
    pub path: PathBuf,
    pub include_in_build: bool,
    /// 记录在哪些配置中被排除 (配置 -> 是否排除)
    pub exclusions: HashMap<BuildConfiguration, bool>,
}

impl SourceFile {
    pub fn new(path: PathBuf) -> Self {
        Self {
            path,
            include_in_build: true,
            exclusions: HashMap::new(),
        }
    }
    
    /// 检查在指定配置中是否被排除
    pub fn is_excluded_in_config(&self, config: &BuildConfiguration) -> bool {
        self.exclusions.get(config).copied().unwrap_or(false)
    }
    
    /// 设置在指定配置中的排除状态
    pub fn set_excluded_in_config(&mut self, config: BuildConfiguration, excluded: bool) {
        self.exclusions.insert(config, excluded);
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomBuildRule {
    pub source_file: PathBuf,
    pub command: String,
    pub outputs: Vec<PathBuf>,
    pub additional_inputs: Vec<String>,
    pub message: Option<String>,
    pub is_moc_file: bool, // 特殊标记，表示这是 Qt MOC 文件
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QtSettings {
    pub enabled: bool,
    pub version: Option<String>,
    pub modules: Vec<String>,
    pub moc_files: Vec<PathBuf>,
    pub ui_files: Vec<PathBuf>,
    pub resource_files: Vec<PathBuf>,
    pub custom_moc_files: Vec<CustomBuildRule>, // 从 CustomBuild 解析的 MOC 文件
    pub tools: QtTools,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QtTools {
    pub moc_exe: Option<PathBuf>,
    pub uic_exe: Option<PathBuf>,
    pub rcc_exe: Option<PathBuf>,
}

impl Default for QtSettings {
    fn default() -> Self {
        Self {
            enabled: false,
            version: None,
            modules: Vec::new(),
            moc_files: Vec::new(),
            ui_files: Vec::new(),
            resource_files: Vec::new(),
            custom_moc_files: Vec::new(),
            tools: QtTools::default(),
        }
    }
}

impl Default for QtTools {
    fn default() -> Self {
        Self {
            moc_exe: None,
            uic_exe: None,
            rcc_exe: None,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BuildSettings {
    pub output_directory: Option<PathBuf>,
    pub intermediate_directory: Option<PathBuf>,
    pub target_name: Option<String>,
    pub preprocessor_definitions: Vec<String>,
    pub include_directories: Vec<PathBuf>,
    pub library_directories: Vec<PathBuf>,
    pub libraries: Vec<String>,
    pub compiler_flags: Vec<String>,
    pub linker_flags: Vec<String>,
    pub language_standard: Option<String>,
    pub qt_settings: QtSettings,
    // 新增的 PropertyGroup 属性
    pub configuration_type: Option<String>,  // Application/DynamicLibrary/StaticLibrary
    pub platform_toolset: Option<String>,   // v120/v141等
    pub character_set: Option<String>,       // Unicode/MultiByte
    pub use_of_mfc: Option<String>,         // Dynamic/Static/false
}

impl Default for BuildSettings {
    fn default() -> Self {
        Self {
            output_directory: None,
            intermediate_directory: None,
            target_name: None,
            preprocessor_definitions: Vec::new(),
            include_directories: Vec::new(),
            library_directories: Vec::new(),
            libraries: Vec::new(),
            compiler_flags: Vec::new(),
            linker_flags: Vec::new(),
            language_standard: None,
            qt_settings: QtSettings::default(),
            configuration_type: None,
            platform_toolset: None,
            character_set: None,
            use_of_mfc: None,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Project {
    pub name: String,
    pub project_type: ProjectType,
    pub source_files: Vec<SourceFile>,
    pub custom_build_rules: Vec<CustomBuildRule>,
    pub configurations: HashMap<BuildConfiguration, BuildSettings>,
    pub dependencies: Vec<String>,
}

impl Project {
    pub fn new(name: String, project_type: ProjectType) -> Self {
        Self {
            name,
            project_type,
            source_files: Vec::new(),
            custom_build_rules: Vec::new(),
            configurations: HashMap::new(),
            dependencies: Vec::new(),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Solution {
    pub name: String,
    pub projects: Vec<Project>,
    /// 原始项目文件所在目录（vcxproj 或 sln 文件所在目录）
    #[serde(skip_serializing_if = "Option::is_none")]
    pub source_directory: Option<PathBuf>,
}

impl Solution {
    pub fn new(name: String) -> Self {
        Self {
            name,
            projects: Vec::new(),
            source_directory: None,
        }
    }

    pub fn with_source_directory(name: String, source_directory: PathBuf) -> Self {
        Self {
            name,
            projects: Vec::new(),
            source_directory: Some(source_directory),
        }
    }
}